#include "world.h"
#include "cell.h"
#include "lifegamerule.h"
#include <algorithm>

World::World(int row, int col)
    : m_row(row), m_col(col)
{
    init(row, col);
}

void World::init(int row, int col) {
    m_cells.resize(row);
    for(int i = 0; i < row; ++i) {
        m_cells[i].resize(col);
        for (int j = 0; j < col; ++j) {
            m_cells[i][j].setStatus(Cell::DEAD);
        }
    }
}
void World::reverseCellStatus(int row, int col) {
    m_cells[row][col].reverseStatus();
}

void World::setCellStatus(int row, int col, Cell::CellStatus status) {
    m_cells[row][col].setStatus(status);
}

const CellContainer& World::getActiveCells() {
    m_cc.clear();
    for (int i = 0; i < m_row; ++i) {
        for (int j = 0; j < m_col; ++j) {
            if (m_cells[i][j].getStatus() == Cell::ALIVE) {
                m_cc.push_back(std::make_pair(i, j));
            }
        }
    }
    return m_cc;
}

void World::step() {
    CellContainer live, death;
    for (int i = 0; i < m_row; ++i) {
        for (int j = 0; j < m_col; ++j) {
            LifeGameRule::JudgeState judge = LifeGameRule::calculate(getNeighbourLive(i, j));
            if (judge == LifeGameRule::BIRTH) {
                    live.push_back(std::make_pair(i, j));
                } else if (judge == LifeGameRule::VANISH) {
                    death.push_back(std::make_pair(i, j));
                }
        }
    }

    for (CellContainer::iterator b = live.begin(), e = live.end(); b != e; ++b) {
        m_cells[(*b).first][(*b).second].setStatus(Cell::ALIVE);
    }

    for (CellContainer::iterator b = death.begin(), e = death.end(); b != e; ++b) {
        m_cells[(*b).first][(*b).second].setStatus(Cell::DEAD);
    }
}




int World::getNeighbourLive(int r, int c) {
    int row = r;
    int col = c;

    int alive = 0;

    for (int i = -1; i < 2; ++i) {
        int curRow = std::min(std::max(row + i, 0), m_row - 1);
        for (int j = -1; j < 2; ++j) {
            if (i == 0 && j == 0) {
                continue;
            }
            int curCol = std::min(std::max(col + j, 0), m_col - 1);
            if (m_cells[curRow][curCol].getStatus() == Cell::ALIVE) {
                ++alive;
            }
        }
    }

    return alive;
}
